package com.devops.admin.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.devops.admin.mapper.DOSProjectEnvClusterNamespaceRelationMapper;
import com.devops.admin.model.DOSClusterNamespace;
import com.devops.admin.model.DOSProjectEnvClusterNamespaceRelation;
import com.devops.admin.model.TableResult;
import com.devops.admin.po.*;
import com.devops.admin.service.DOSProjectEnvClusterNamespaceRelationService;
import com.devops.admin.util.Assert;
import com.devops.shiro.vm.BaseUserVM;
import org.apache.shiro.SecurityUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @ClassName DOSProjectEnvClusterNamespaceRelationServiceImpl
 * @Description TODO
 * @Author hepingguo
 * @Date 2022/6/20 17:51
 * @Version 1.0
 **/
@Service
public class DOSProjectEnvClusterNamespaceRelationServiceImpl
        extends ServiceImpl<DOSProjectEnvClusterNamespaceRelationMapper, DOSProjectEnvClusterNamespaceRelation>
    implements DOSProjectEnvClusterNamespaceRelationService {

    @Override
    public Boolean authorizeProject(List<DOSProjectEnvClusterNamespaceRelation> authorizes) {
        BaseUserVM user = (BaseUserVM) SecurityUtils.getSubject().getPrincipal();
        //此处无需权限校验 graphql层已经添加注解 只有管理员和超管能进行授权
        Assert.isTrue(CollectionUtil.isNotEmpty(authorizes), "授权条件不能为空");

        Integer projectId = authorizes.get(0).getProjectId();
        LambdaQueryWrapper<DOSProjectEnvClusterNamespaceRelation> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DOSProjectEnvClusterNamespaceRelation::getProjectId, projectId);
        List<DOSProjectEnvClusterNamespaceRelation> namespaceRelations = this.list(queryWrapper);

        List<DOSProjectEnvClusterNamespaceRelation> newAuthorizes = new ArrayList<>();
        List<DOSProjectEnvClusterNamespaceRelation> oldAuthorizes = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(namespaceRelations)) {
            // 收集新添加的集群
            for (DOSProjectEnvClusterNamespaceRelation authorize : authorizes) {
                boolean bool = true;
                for (DOSProjectEnvClusterNamespaceRelation relation : namespaceRelations) {
                    if (authorize.getClusterId().intValue() == relation.getClusterId().intValue()
                            && authorize.getNamespaceId().intValue() == relation.getNamespaceId().intValue()) {
                        bool = false;
                        break;
                    }
                }
                if (bool) {
                    newAuthorizes.add(authorize);
                }
            }

            // 收集需要删除的集群信息
            for (DOSProjectEnvClusterNamespaceRelation relation : namespaceRelations) {
                boolean bool = true;
                for (DOSProjectEnvClusterNamespaceRelation authorize : authorizes) {
                    if (relation.getClusterId().intValue() == authorize.getClusterId().intValue()
                            && relation.getNamespaceId().intValue() == authorize.getNamespaceId().intValue()) {
                        bool = false;
                        break;
                    }
                }

                if (bool) {
                    oldAuthorizes.add(relation);
                }
            }

            if (CollectionUtil.isNotEmpty(newAuthorizes)) {
                this.saveBatch(newAuthorizes);
            }
            // 删除不需要的集群授权
            if (CollectionUtil.isNotEmpty(oldAuthorizes)) {
                List<Integer> oldClusterIds = oldAuthorizes.stream().map(DOSProjectEnvClusterNamespaceRelation::getClusterId)
                        .collect(Collectors.toList());
                List<Integer> namespaceIds = oldAuthorizes.stream().map(DOSProjectEnvClusterNamespaceRelation::getNamespaceId)
                        .collect(Collectors.toList());
                LambdaQueryWrapper<DOSProjectEnvClusterNamespaceRelation> deleteWrapper = new LambdaQueryWrapper<>();
                deleteWrapper.in(DOSProjectEnvClusterNamespaceRelation::getClusterId, oldClusterIds)
                        .in(DOSProjectEnvClusterNamespaceRelation::getNamespaceId, namespaceIds)
                        .eq(DOSProjectEnvClusterNamespaceRelation::getProjectId, projectId);
                this.remove(deleteWrapper);
            }

            return true;
        }
        // 项目初次授权
        return this.saveBatch(authorizes);
    }

    @Override
    public List<DOSProjectEvnClusterPo> getAuthorizationInfo(Integer projectId) {

        return baseMapper.selectAuthorized(projectId);
    }

    @Override
    public List<DOSProjectEvnClusterPo> getEnvClusters(List<Integer> projectIds) {
        return baseMapper.selectEnvClusters(projectIds);
    }

    @Override
    public List<DOSProjectEnvTypePo> getSelectEnvType(Integer projectId) {
        return baseMapper.selectEnvType(projectId);
    }

    @Override
    public List<DOSClusterNamespacePo> getClustersByProjectIdAndEnvType(Integer projectId, Integer envType) {
        Assert.isTrueMvc(projectId != null && projectId > 0, "projectId不能为空");
//        Assert.isTrueMvc(envType != null && envType > 0, "envType不能为空");
        List<DOSProjectEnvClusterNamespaceRelationPo> dosProjectEnvClusterNamespaceRelationPoList =
                baseMapper.getClusterNamespaceByProjectIdAndEnvType(projectId, envType);
        Map<Integer, List<DOSProjectEnvClusterNamespaceRelationPo>> groupMap = dosProjectEnvClusterNamespaceRelationPoList
                .stream().collect(Collectors.groupingBy(DOSProjectEnvClusterNamespaceRelationPo::getClusterId));
        List<DOSClusterNamespacePo> clusters = new ArrayList<>();
        groupMap.forEach((k, v) -> {
            DOSClusterNamespacePo dosClusterNamespacePo = DOSClusterNamespacePo.builder().clusterId(k).build();
            List<DOSClusterNamespace> namespaces = new ArrayList<>();
            v.forEach(po -> {
                DOSClusterNamespace namespace = DOSClusterNamespace.builder()
                        .namespace(po.getNamespace()).id(po.getNamespaceId()).build();
                namespaces.add(namespace);
                if (StrUtil.isBlank(dosClusterNamespacePo.getClusterName())) {
                    dosClusterNamespacePo.setClusterName(po.getClusterName());
                }
            });
            dosClusterNamespacePo.setNamespaces(namespaces);

            clusters.add(dosClusterNamespacePo);
        });
        return clusters;
    }
}
